package com.chenyanqing.model.two.factory;

import com.chenyanqing.model.two.annotation.AnnotationTypeConfig;
import com.chenyanqing.model.two.annotation.Autowired;
import com.chenyanqing.model.two.annotation.Transactional;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BeanFactory {

    private BeanFactory(){
    }

    private static BeanFactory beanFactory = new BeanFactory();
    public static BeanFactory  getBeanFactory(){
        return  beanFactory;
    }


    private static Map<String,Object> map = new HashMap<>();


    /*
     * @param classname
     * @param <T>
     * @return
     * @throws ClassNotFoundException
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public <T> T createBean(String classname,String beanMapId) throws ClassNotFoundException, IllegalAccessException, InstantiationException {

        //初始化bean
        T t = beanInit(classname);

        //bean创建后，处理注解逻辑，创建代理对象
        t = (T)AnnotationAspectJAutoProxyCreator.getInstance().processAnnotationAspectProxy(t);


        //存储到map
        if(t!=null) {
            map.put(beanMapId, t);
        }

        return t;
    }
    /*
     * @param classname
     * @param <T>
     * @return
     * @throws ClassNotFoundException
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public <T> T createBean(String classname) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
       return createBean(classname,classname);
    }



    private <T> T beanInit(String classname) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class<?> aClass = Class.forName(classname);
        if (aClass != null) {
            //创建对象
            Object object = aClass.newInstance();
            //遍历对象中是否存在autowired注解依赖注入，有则获得依赖对象并赋值
            Field[] declaredFields = aClass.getDeclaredFields();
            if (declaredFields != null) {
                for (Field declaredField : declaredFields) {
                    Autowired annotation = declaredField.getAnnotation(Autowired.class);
                    if (annotation != null) {
                        if (isPrimitive(declaredField)) {
                            throw new RuntimeException("Autowired注解只能在对象属性上添加，不能在基本类型添加");
                        } else {
                            String fieldClassname = declaredField.getType().getName();
                            Object fieldObject = map.get(fieldClassname);
                            if (fieldObject == null) {
                                fieldObject = createBean(fieldClassname);
                            }
                            //给object的该属性注入依赖对象，也就是给auowired注解的属性赋值
                            declaredField.setAccessible(true);
                            declaredField.set(object, fieldObject);

                        }
                    }
                }
            }
            return (T) object;
        }
        return null;

    }


    public <T> T getBeanById(String beanId) {
          Object  object =  map.get(beanId);
          if(object!=null){
              return (T) object;
          }else{
             return null;
          }
    }



    private boolean isPrimitive(Object obj) {
        try {
            return ((Class<?>)obj.getClass().getField("TYPE").get(null)).isPrimitive();
        } catch (Exception e) {
            return false;
        }
    }




}
